// Copyright (C) 1953-2022 NUDT
// Verilog module name - diagest_delay_manage 
// Version:V4.0.0.20220524
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         send the md delayed
//         avoid reading pkt data before it is written to the bufm
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module diagest_delay_manage #(parameter delay_cycle = 5'd10)
(
       i_clk,
       i_rst_n,
       
       iv_md,
       i_md_wr,
       o_md_ack,
       
       ov_md,
       o_md_wr,
       i_md_ack
);

// I/O
// clk & rst
input                  i_clk;                   //125Mhz
input                  i_rst_n;

input      [299:0]     iv_md;
input                  i_md_wr;
output  reg               o_md_ack;

output reg [299:0]     ov_md;
output reg             o_md_wr;
input                  i_md_ack;
// internal reg&wire for state machine
wire                w_mdfifo_empty_fifo2tlu ;
reg                 r_mdfifo_rd_tlu2fifo    ;
wire   [299:0]      wv_mdfifo_rdata_fifo2tlu;

reg                 r_validfifo_wr_fifo2tlu    ;
reg                 r_validfifo_wdata_fifo2tlu ;
wire                w_validfifo_empty_fifo2tlu ;
reg                 r_validfifo_rd_tlu2fifo    ;
wire                wv_validfifo_rdata_fifo2tlu;  

//assign  o_md_ack = i_md_ack;
//////////////////////////////////////////////////
//                  delay                       //
//////////////////////////////////////////////////
reg        [31:0]      rv_delay_cycles;
always @(posedge i_clk or negedge i_rst_n) begin
    if(i_rst_n == 1'b0)begin
        rv_delay_cycles              <= 32'b0;
		 
		r_validfifo_wr_fifo2tlu      <= 1'b0;
		r_validfifo_wdata_fifo2tlu   <= 1'b0;
		
		o_md_ack                     <= 1'b0;
    end
    else begin
	    rv_delay_cycles       <= {rv_delay_cycles[30:0],i_md_wr};
		
		if(i_md_wr&(!o_md_ack))begin
		    o_md_ack <= 1'b1;
		end
		else begin
		    o_md_ack <= 1'b0;
		end
		
        if(rv_delay_cycles[delay_cycle] == 1'b1)begin
			r_validfifo_wr_fifo2tlu      <= 1'b1;
			r_validfifo_wdata_fifo2tlu   <= 1'b1;		
		end
		else begin
			r_validfifo_wr_fifo2tlu      <= 1'b0;
			r_validfifo_wdata_fifo2tlu   <= 1'b0;		
		end
	end
end
//////////////////////////////////////////////////
//                  state                       //
//////////////////////////////////////////////////
reg        [1:0]       ddm_state;
localparam             IDLE_S        = 2'd0,
                       OUTPUT_MD_S   = 2'd1,
					   WAIT_ACK_S    = 2'd2;
always @(posedge i_clk or negedge i_rst_n) begin
    if(i_rst_n == 1'b0)begin
        ov_md       <= 300'h0;
        o_md_wr     <= 1'h0;
		
		r_mdfifo_rd_tlu2fifo <= 1'b0;
		r_validfifo_rd_tlu2fifo <= 1'b0;
        
        ddm_state           <= IDLE_S;
    end
    else begin
        case(ddm_state)
            IDLE_S:begin//receive md 
		//		ov_md       <= 200'h0;
				o_md_wr     <= 1'h0;			
                if(w_validfifo_empty_fifo2tlu == 1'b0)begin
                    if(w_mdfifo_empty_fifo2tlu == 1'b0)begin
					    r_mdfifo_rd_tlu2fifo <= 1'b1;
						r_validfifo_rd_tlu2fifo <= 1'b1;
						ddm_state  <= OUTPUT_MD_S;
					end
                    else begin
					    r_mdfifo_rd_tlu2fifo <= 1'b0;
						r_validfifo_rd_tlu2fifo <= 1'b0;
						ddm_state           <= IDLE_S;
					end
                end
                else begin
				    r_mdfifo_rd_tlu2fifo <= 1'b0;
					r_validfifo_rd_tlu2fifo <= 1'b0;
                    ddm_state           <= IDLE_S;
                end
            end
            
            OUTPUT_MD_S:begin 
				ov_md       <= wv_mdfifo_rdata_fifo2tlu;
				o_md_wr     <= 1'b1;
				
				r_mdfifo_rd_tlu2fifo <= 1'b0;
				
				ddm_state           <= WAIT_ACK_S;
            end
            WAIT_ACK_S:begin
			    if(i_md_ack)begin//receive
				    o_md_wr     <= 1'b0;
					ddm_state           <= IDLE_S;
				end
				else begin
				    ddm_state           <= WAIT_ACK_S;
				end
			end
            default:begin
           //     ov_md       <= 200'h0;
                o_md_wr     <= 1'h0;

                r_mdfifo_rd_tlu2fifo <= 1'b0;
                ddm_state           <= IDLE_S;
            end
        endcase
    end
end
//`ifdef altera_ip
syncfifo_showahead_sclr_w300d32 syncfifo_showahead_sclr_w300d32_ddm_inst(
	.data  (iv_md), 
	.wrreq (o_md_ack),
	.rdreq (r_mdfifo_rd_tlu2fifo),
	.clock (i_clk),
	.sclr  (!i_rst_n), 
	.q     (wv_mdfifo_rdata_fifo2tlu),    
	.usedw (),
	.full  (), 
	.empty (w_mdfifo_empty_fifo2tlu) 
);

syncfifo_showahead_sclr_w1d32 syncfifo_showahead_sclr_w1d32_ddm_inst(
	.data  (r_validfifo_wr_fifo2tlu), 
	.wrreq (r_validfifo_wdata_fifo2tlu),
	.rdreq (r_validfifo_rd_tlu2fifo),
	.clock (i_clk),
	.aclr  (!i_rst_n), 
	.q     (wv_validfifo_rdata_fifo2tlu),    
	.usedw (),
	.full  (), 
	.empty (w_validfifo_empty_fifo2tlu) 
);
//`endif
`ifdef xilinx_ip
syncfifo_showahead_sclr_w200d32 syncfifo_showahead_sclr_w200d32_ddm_inst(
.srst      (!i_rst_n),                    //Reset the all signal
.din       (iv_md),                       //The Inport of data 
.rd_en     (r_mdfifo_rd_tlu2fifo),       //active-high
.clk       (i_clk),                       //ASYNC WriteClk(), SYNC use wrclk
.wr_en     (o_md_ack),                     //active-high
.dout      (wv_mdfifo_rdata_fifo2tlu),   //The output of data
.full      (),                            //Write domain full 
.empty     (w_mdfifo_empty_fifo2tlu),    //Write domain empty
.data_count()                            //Read-usedword
);

syncfifo_showahead_sclr_w1d32 syncfifo_showahead_sclr_w1d32_ddm_inst(
.srst      (!i_rst_n),                    //Reset the all signal
.din       (r_validfifo_wr_fifo2tlu),                       //The Inport of data 
.rd_en     (r_validfifo_rd_tlu2fifo),       //active-high
.clk       (i_clk),                       //ASYNC WriteClk(), SYNC use wrclk
.wr_en     (r_validfifo_wdata_fifo2tlu),                     //active-high
.dout      (wv_validfifo_rdata_fifo2tlu),   //The output of data
.full      (),                            //Write domain full 
.empty     (w_validfifo_empty_fifo2tlu),    //Write domain empty
.data_count()                            //Read-usedword
);
`endif
endmodule